/*
 * Copyright (c) Hisilicon Technologies Co., Ltd. 2018-2019. All rights reserved.
 * Description:hal watchDog interface
 * Author:IP Camera Reference Develop Team
 * Create:2018/12/28
 */

#include "hi_hal_watchdog.h"
#include <linux/interrupt.h>
#include "hi_type.h"
//#include "hi_product_comm.h"
#include "hi_appcomm_log.h"

#ifdef __cplusplus
#if __cplusplus
extern "C" {
#endif
#endif /* End of #ifdef __cplusplus */

#define WDG_BASE_ADDR 0x12030000

#define WDG_LOAD    (WDG_BASE_ADDR + 0x0000)
#define WDG_VALUE   (WDG_BASE_ADDR + 0x0004)
#define WDG_CONTROL (WDG_BASE_ADDR + 0x0008)
#define WDG_INTCLR  (WDG_BASE_ADDR + 0x000C)
#define WDG_RIS     (WDG_BASE_ADDR + 0x0010)
#define WDG_MIS     (WDG_BASE_ADDR + 0x0014)
#define WDG_LOCK    (WDG_BASE_ADDR + 0x0C00)

#define WDG_ENABLE_MSK  0x3
#define WDG_DISABLE_MSK 0x0

/* any num could lock watchdog */
#define WDG_LOCK_MSK   0x0
#define WDG_UNLOCK_MSK 0x1ACCE551

#define WDG_INT_NUM 34

/* watch dog clock : 3M */
#define WDG_CLK (3 * 1024 * 1024)
/* watch dog timeout second, soc will reset if no int clear after 20s */
#define WDG_TIMEOUT     5
#define WDG_TIMEOUT_NUM ((WDG_CLK) * (WDG_TIMEOUT))

static irqreturn_t HAL_WDG_IRQHandler(HI_S32 irq, HI_VOID *data)
{
    MLOGW("system wdg!\n");
    
    return IRQ_HANDLED;
}

static HI_VOID HAL_WDG_PrintVal(HI_VOID)
{
    HI_U32 dogVal = readl(WDG_VALUE);
    MLOGD("start dog timer val: %d\n", dogVal);
}

HI_S32 HI_HAL_WDG_Init(HI_VOID)
{
    HI_S32 ret = request_irq(WDG_INT_NUM, HAL_WDG_IRQHandler, 0, HI_NULL, HI_NULL);
    if (ret != HI_SUCCESS) {
        MLOGE(RED "request_irq failed Ret: %x\n\n" NONE, ret);
        return ret;
    }

    enable_irq(WDG_INT_NUM);

    /* set timeout num */
    writel(WDG_TIMEOUT_NUM, WDG_LOAD);
    /* enable watch dog */
    writel(WDG_ENABLE_MSK, WDG_CONTROL);
    HAL_WDG_PrintVal();

    /* lock watch dog reg to avoid writing */
    writel(WDG_LOCK_MSK, WDG_LOCK);

    return HI_SUCCESS;
}

HI_VOID HI_HAL_WDG_DeInit(HI_VOID)
{
    /* disable watch dog */
    writel(WDG_DISABLE_MSK, WDG_CONTROL);

    disable_irq(WDG_INT_NUM);

    free_irq(WDG_INT_NUM, HI_NULL);
}

HI_VOID HI_HAL_WDG_ClearIRQ(HI_VOID)
{
    /* unlock watch dog reg write permission */
    writel(WDG_UNLOCK_MSK, WDG_LOCK);

    /* clear watchdog interrupt for feed dog */
    writel(0, WDG_INTCLR);

    /* lock again */
    writel(WDG_LOCK_MSK, WDG_LOCK);
}

#ifdef __cplusplus
#if __cplusplus
}
#endif
#endif /* End of #ifdef __cplusplus */

